/** 
 * @Description: 缓冲区分析工具
 * @Author: 程前
 * @Date: 2025-01-21 09:13:09
 * @LastEditors: 程前
 * @LastEditTime: 2025-01-21 14:25:22
 */

import { Viewer, Entity, Cartesian3, Color, PolygonHierarchy, HeightReference, LabelStyle, VerticalOrigin, HorizontalOrigin, Cartesian2, CallbackProperty, ScreenSpaceEventHandler, ScreenSpaceEventType } from "cesium";
import { buffer as TurfBuffer, point as TurfPoint, lineString as TurfLineString } from "@turf/turf";
import { transformCartesianToWGS84, setEventByHandler, removeEventByHandler } from "@/utils";

interface AnalysisInstance {
    clear: () => void;
}

interface TurfFeature {
    type: string;
    geometry: {
        type: string;
        coordinates: number[][][] | number[][];
    };
    properties: any;
}

export interface BufferAnalysisOptions {
    viewer: Viewer;
    type: 'point' | 'line';
    radius: number;
    color?: Color;
}

export class BufferAnalysis implements AnalysisInstance {
    private viewer: Viewer;
    private type: 'point' | 'line';
    private radius: number;
    private color: Color;
    private positions: Cartesian3[] = [];
    private tempPosition: Cartesian3 | null = null;
    private entities: Entity[] = [];
    private currentEntity: Entity | null = null;
    private isDrawing: boolean = false;
    private handler: ScreenSpaceEventHandler | null = null;

    constructor(options: BufferAnalysisOptions) {
        this.viewer = options.viewer;
        this.type = options.type;
        this.radius = options.radius;
        this.color = options.color || Color.YELLOW.withAlpha(0.5);
        this.handler = null;
    }

    /**
     * 开始绘制
     */
    public startDraw(): void {
        this.isDrawing = true;
        this.handler = new ScreenSpaceEventHandler(this.viewer.scene.canvas);
        if (this.type === 'point') {
            this.drawPointBuffer();
        } else {
            this.drawLineBuffer();
        }
    }

    /**
     * 绘制点缓冲区
     */
    private drawPointBuffer(): void {
        if (!this.handler) return;

        // 鼠标左键点击事件
        const leftClick = (event: any) => {
            const cartesian = this.viewer.scene.pickPosition(event.position);
            if (!cartesian) return;

            // 添加点实体
            const pointEntity = this.viewer.entities.add({
                position: cartesian,
                point: {
                    pixelSize: 4,
                    color: Color.YELLOW,
                    outlineColor: Color.WHITE,
                    outlineWidth: 2,
                    // heightReference: HeightReference.CLAMP_TO_GROUND
                    disableDepthTestDistance: Number.POSITIVE_INFINITY // 禁用深度测试，确保点始终可见
                }
            });
            this.entities.push(pointEntity);

            // 创建缓冲区
            const wgs84 = transformCartesianToWGS84(cartesian);
            const point = TurfPoint([wgs84.lng, wgs84.lat]);
            const buffered = TurfBuffer(point, this.radius / 1000) as TurfFeature; // turf使用公里为单位

            // 提取缓冲区边界坐标
            const coordinates = buffered.geometry.coordinates[0] as number[][];
            const positions: Cartesian3[] = coordinates.map(coord => {
                return Cartesian3.fromDegrees(coord[0], coord[1], wgs84.alt);
            });

            // 创建缓冲区多边形
            const bufferEntity = this.viewer.entities.add({
                polygon: {
                    hierarchy: new PolygonHierarchy(positions),
                    material: this.color,
                    outline: true,
                    outlineColor: Color.YELLOW,
                    outlineWidth: 2,
                    heightReference: HeightReference.CLAMP_TO_GROUND
                }
            });
            this.entities.push(bufferEntity);

            // 添加半径标签
            const labelEntity = this.viewer.entities.add({
                position: cartesian,
                label: {
                    text: `半径: ${this.radius}米`,
                    font: '16px sans-serif',
                    fillColor: Color.WHITE,
                    outlineColor: Color.BLACK,
                    outlineWidth: 1,
                    style: LabelStyle.FILL_AND_OUTLINE,
                    verticalOrigin: VerticalOrigin.BOTTOM,
                    horizontalOrigin: HorizontalOrigin.CENTER,
                    pixelOffset: new Cartesian2(0, -10),
                    disableDepthTestDistance: Number.POSITIVE_INFINITY // 禁用深度测试，确保点始终可见
                }
            });
            this.entities.push(labelEntity);

            // 保持绘制状态，允许继续绘制新的点缓冲区
            this.isDrawing = true;
        }
        setEventByHandler(this.handler, leftClick, ScreenSpaceEventType.LEFT_CLICK);
    }

    /**
     * 绘制线缓冲区
     */
    private drawLineBuffer(): void {
        if (!this.handler) return;

        // 创建动态线实体
        const createDynamicLine = () => {
            if (this.currentEntity) {
                this.viewer.entities.remove(this.currentEntity);
            }
            this.currentEntity = this.viewer.entities.add({
                polyline: {
                    positions: new CallbackProperty(() => {
                        return this.tempPosition ?
                            [...this.positions, this.tempPosition] :
                            this.positions;
                    }, false),
                    width: 2,
                    material: Color.YELLOW,
                    clampToGround: true
                }
            });
            return this.currentEntity;
        };

        // 鼠标左键点击事件
        const leftClick = (event: any) => {
            const cartesian = this.viewer.scene.pickPosition(event.position);
            if (!cartesian) return;

            this.positions.push(cartesian);

            // 添加点实体
            const pointEntity = this.viewer.entities.add({
                position: cartesian,
                point: {
                    pixelSize: 8,
                    color: Color.YELLOW,
                    outlineColor: Color.WHITE,
                    outlineWidth: 2,
                    disableDepthTestDistance: Number.POSITIVE_INFINITY // 禁用深度测试，确保点始终可见
                }
            });
            this.entities.push(pointEntity);

            // 创建或更新动态线
            if (this.positions.length === 1) {
                createDynamicLine();
            }
        }
        setEventByHandler(this.handler, leftClick, ScreenSpaceEventType.LEFT_CLICK);

        // 鼠标移动事件
        const mouseMove = (event: any) => {
            if (this.positions.length === 0) return;
            const cartesian = this.viewer.scene.pickPosition(event.endPosition);
            if (cartesian) {
                this.tempPosition = cartesian;
            }
        }
        setEventByHandler(this.handler, mouseMove, ScreenSpaceEventType.MOUSE_MOVE);


        // 鼠标右键点击事件（完成绘制）
        const rightClick = () => {
            if (this.positions.length < 2) return;

            // 移除动态线
            if (this.currentEntity) {
                this.viewer.entities.remove(this.currentEntity);
            }

            // 创建线缓冲区
            const lineCoordinates = this.positions.map(position => {
                const wgs84 = transformCartesianToWGS84(position);
                return [wgs84.lng, wgs84.lat] as [number, number];
            });

            // 创建中心线
            const centerLine = this.viewer.entities.add({
                polyline: {
                    positions: this.positions,
                    width: 2,
                    material: Color.YELLOW,
                    clampToGround: true
                }
            });
            this.entities.push(centerLine);

            const line = TurfLineString(lineCoordinates);
            const buffered = TurfBuffer(line, this.radius / 1000) as TurfFeature; // turf使用公里为单位

            // 提取缓冲区边界坐标
            const coordinates = buffered.geometry.coordinates[0] as number[][];
            const bufferPositions: Cartesian3[] = coordinates.map(coord => {
                return Cartesian3.fromDegrees(coord[0], coord[1]);
            });

            // 创建缓冲区多边形
            const bufferEntity = this.viewer.entities.add({
                polygon: {
                    hierarchy: new PolygonHierarchy(bufferPositions),
                    material: this.color,
                    outline: true,
                    outlineColor: Color.YELLOW,
                    outlineWidth: 2,
                    heightReference: HeightReference.CLAMP_TO_GROUND
                }
            });
            this.entities.push(bufferEntity);

            // 添加半径标签
            const centerPosition = Cartesian3.fromDegrees(
                lineCoordinates[Math.floor(lineCoordinates.length / 2)][0],
                lineCoordinates[Math.floor(lineCoordinates.length / 2)][1]
            );
            const labelEntity = this.viewer.entities.add({
                position: centerPosition,
                label: {
                    text: `缓冲区宽度: ${this.radius}米`,
                    font: '16px sans-serif',
                    fillColor: Color.WHITE,
                    outlineColor: Color.BLACK,
                    outlineWidth: 2,
                    style: LabelStyle.FILL_AND_OUTLINE,
                    verticalOrigin: VerticalOrigin.BOTTOM,
                    horizontalOrigin: HorizontalOrigin.CENTER,
                    pixelOffset: new Cartesian2(0, -10),
                    heightReference: HeightReference.CLAMP_TO_TERRAIN,
                    disableDepthTestDistance: Number.POSITIVE_INFINITY // 确保标签始终可见
                }
            });
            this.entities.push(labelEntity);

            // 清理状态，但保持事件处理器
            this.positions = [];
            this.tempPosition = null;
            this.currentEntity = null;
            this.isDrawing = true;  // 保持绘制状态为true，以便继续绘制
        }

        setEventByHandler(this.handler, rightClick, ScreenSpaceEventType.RIGHT_CLICK);
    }

    /**
     * 清理所有实体
     */
    public clear(): void {
        this.entities.forEach(entity => {
            this.viewer.entities.remove(entity);
        });
        this.entities = [];
        if (this.currentEntity) {
            this.viewer.entities.remove(this.currentEntity);
            this.currentEntity = null;
        }
        this.positions = [];
        this.tempPosition = null;
        this.isDrawing = false;
    }

    /**
     * 设置缓冲区半径
     */
    public setRadius(radius: number): void {
        this.radius = radius;
    }

    /**
     * 设置缓冲区颜色
     */
    public setColor(color: Color): void {
        this.color = color;
    }

    /**
     * 是否正在绘制
     */
    public isActive(): boolean {
        return this.isDrawing;
    }

    /**
     * 销毁事件处理器
     */
    public destroyHandler(): void {
        if (this.handler) {
            this.handler.destroy();
            this.handler = null;
        }
    }
}
